﻿#include "FITKAbaqusHDF5AdaptorAmplitude.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractAmplitude.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudePeriodic.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeTabular.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorAmplitude::getAdaptorClass()
    {
        //适配器名称
        return "FITKAbaqusHDF5AdaptorAmplitude";
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::adaptR()
    {
        Interface::FITKAbaAbstractAmplitude* amplitude = dynamic_cast<Interface::FITKAbaAbstractAmplitude*>(_dataObj);
        if (!amplitude || !_reader)return false;
        bool isR = true;
        //读取幅值
        isR &= readAmplitude(amplitude, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::adaptW()
    {
        Interface::FITKAbaAbstractAmplitude* amplitude = dynamic_cast<Interface::FITKAbaAbstractAmplitude*>(_dataObj);
        if (!amplitude || !_writer)return false;
        bool isW = true;
        //写出幅值
        isW &= writeAmplitude(amplitude, *_h5Group);
        return isW;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::readAmplitude(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        if (!amplitude) return false;
        bool isR = true;
        isR &= readNDataObject(amplitude, h5Group);

        auto ampType = amplitude->getAmplitudeType();
        if (ampType == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Periodic)
        {
            isR &= readAmplitudePeriodic(amplitude, h5Group);
        }
        else if (ampType == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Tabular)
        {
            isR &= readAmplitudeTabular(amplitude, h5Group);
        }
        else
        {
            return false;
        }
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::readAmplitudePeriodic(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        //写出周期类型
        Interface::FITKAbaAmplitudePeriodic* amplitudePeriodic = dynamic_cast<Interface::FITKAbaAmplitudePeriodic*>(amplitude);
        if (!amplitudePeriodic || !_reader)return false;

        //FITKAbaAmplitudePeriodic
        auto TimeSpan = readStrAttribute(h5Group, "TimeSpan");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::TimeSpan> fitkTypeTrafer;
        bool isValid = false;
        //写出类型
        auto timeSpanType = fitkTypeTrafer.fromString(QString::fromStdString(TimeSpan), isValid);
        if (!isValid) return false;
        amplitudePeriodic->setTimeSpan(timeSpanType);

        double CircularFrequency = readDoubleAttribute(h5Group, "CircularFrequency");
        amplitudePeriodic->setCircularFrequency(CircularFrequency);

        double StartingTime = readDoubleAttribute(h5Group, "StartingTime");
        amplitudePeriodic->setStartingTime(StartingTime);

        double InitialAmplitude = readDoubleAttribute(h5Group, "InitialAmplitude");
        amplitudePeriodic->setInitialAmplitude(InitialAmplitude);

        int NumberOfRows = readIntAttribute(h5Group, "NumberOfRows");
        amplitudePeriodic->setNumberOfRows(NumberOfRows);


        for (int i = 0; i < NumberOfRows; ++i)
        {
            QString childName = "Rows_" + QString::number(i);
            if (!h5Group.attrExists(childName.toStdString())) return false;
            auto child = h5Group.openGroup(childName.toStdString());

            double A = readDoubleAttribute(child, "A");
            double B = readDoubleAttribute(child, "B");
            amplitudePeriodic->setA(A, i);
            amplitudePeriodic->setB(B, i);
        }

        return true;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::readAmplitudeTabular(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        //写出表格类型
        Interface::FITKAbaAmplitudeTabular* amplitudeTabular = dynamic_cast<Interface::FITKAbaAmplitudeTabular*>(amplitude);
        if (!amplitudeTabular || !_reader)return false;
        bool isValid = false;

        //FITKAbaAmplitudePeriodic
        auto TimeSpan = readStrAttribute(h5Group, "TimeSpan");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::TimeSpan> fitkTypeTrafer;
        auto timeSpanType = fitkTypeTrafer.fromString(QString::fromStdString(TimeSpan), isValid);
        if (!isValid) return false;
        amplitudeTabular->setTimeSpan(timeSpanType);

        auto smoothingType = readStrAttribute(h5Group, "SmoothingType");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::SmoothingType> fitkSmoothingTypeTrafer;
        //写出类型
        auto eSmoothingType = fitkSmoothingTypeTrafer.fromString(QString::fromStdString(smoothingType), isValid);
        if (!isValid) return false;
        amplitudeTabular->setSmoothingType(eSmoothingType);

        double smoothingValue = readDoubleAttribute(h5Group, "SmoothingValue");
        amplitudeTabular->setSmoothingValue(smoothingValue);

        auto baseLineCorrection = readStrAttribute(h5Group, "BaseLineCorrection");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::BaselineCorrection> fitkbaseLineCorrectionTypeTrafer;
        auto eBaseLineCorrection = fitkbaseLineCorrectionTypeTrafer.fromString(QString::fromStdString(baseLineCorrection), isValid);
        if (!isValid) return false;
        amplitudeTabular->setBaseLineCorrection(eBaseLineCorrection);

        int NumberOfRows = readIntAttribute(h5Group, "NumberOfRows");
        amplitudeTabular->setNmberOfRows(NumberOfRows);
        for (int i = 0; i < NumberOfRows; ++i)
        {
            QString childName = "Rows_" + QString::number(i);
            if (!h5Group.nameExists(childName.toStdString())) return false;
            auto child = h5Group.openGroup(childName.toStdString());

            double Time = readDoubleAttribute(child, "Time");
            amplitudeTabular->setTime(Time, i);
            double Amplitude = readDoubleAttribute(child, "Amplitude");
            amplitudeTabular->setAmplitude(Amplitude, i);
        }
        int NumberOfRowsOfMultipleIntervals = readIntAttribute(h5Group, "NumberOfRowsOfMultipleIntervals");
        amplitudeTabular->setNumberOfRowsOfMultipleIntervals(NumberOfRowsOfMultipleIntervals);
        for (int i = 0; i < NumberOfRowsOfMultipleIntervals; ++i)
        {
            QString childName = "MultipleIntervalRows_" + QString::number(i);
            if (!h5Group.nameExists(childName.toStdString())) return false;
            auto child = h5Group.openGroup(childName.toStdString());

            double MultipleInterval = readDoubleAttribute(child, "MultipleInterval");
            amplitudeTabular->setMultipleInterval(MultipleInterval, i);
        }
        return true;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::writeAmplitude(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        if (!amplitude) return false;
        bool isW = true;

        std::string groupName = createParentAttribute(amplitude, h5Group);
        if (groupName.empty())return false;

        _h5CreateGroup = h5Group.createGroup(groupName);

        auto ampType = amplitude->getAmplitudeType();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType> fitkTypeTrafer;
        bool isValid = false;
        //写出类型
        QString TypeStr = fitkTypeTrafer.toStrting(ampType, isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "AmplitudeType", TypeStr.toStdString());

        if (ampType == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Periodic)
        {
            isW &= writeAmplitudePeriodic(amplitude, _h5CreateGroup);
        }
        else if (ampType == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Tabular)
        {
            isW &= writeAmplitudeTabular(amplitude, _h5CreateGroup);
        }
        else
        {
            return false;
        }
        isW &= writeNDataObject(amplitude, _h5CreateGroup);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::writeAmplitudePeriodic(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        //写出周期类型
        Interface::FITKAbaAmplitudePeriodic* amplitudePeriodic = dynamic_cast<Interface::FITKAbaAmplitudePeriodic*>(amplitude);
        if (!amplitudePeriodic || !_writer)return false;

        auto TimeSpan = amplitudePeriodic->getTimeSpan();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::TimeSpan> fitkTypeTrafer;
        bool isValid = false;
        //写出类型
        QString TypeStr = fitkTypeTrafer.toStrting(TimeSpan, isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "TimeSpan", TypeStr.toStdString());

        double CircularFrequency = amplitudePeriodic->getCircularFrequency();
        writeDoubleAttribute(h5Group, "CircularFrequency", &CircularFrequency);
        double StartingTime = amplitudePeriodic->getStartingTime();
        writeDoubleAttribute(h5Group, "StartingTime", &StartingTime);
        double InitialAmplitude = amplitudePeriodic->getInitialAmplitude();
        writeDoubleAttribute(h5Group, "InitialAmplitude", &InitialAmplitude);
        int NumberOfRows = amplitudePeriodic->getNumberOfRows();
        writeIntAttribute(h5Group, "NumberOfRows", &NumberOfRows);

        for (int i = 0; i < NumberOfRows; ++i)
        {
            QString childName = "Rows_" + QString::number(i);
            auto child = h5Group.createGroup(childName.toStdString());

            double A = amplitudePeriodic->getA(i);
            writeDoubleAttribute(child, "A", &A);
            double B = amplitudePeriodic->getB(i);
            writeDoubleAttribute(child, "B", &B);
        }

        return true;
    }

    bool FITKAbaqusHDF5AdaptorAmplitude::writeAmplitudeTabular(Interface::FITKAbaAbstractAmplitude* amplitude, H5::Group& h5Group)
    {
        //写出表格类型
        Interface::FITKAbaAmplitudeTabular* amplitudeTabular = dynamic_cast<Interface::FITKAbaAmplitudeTabular*>(amplitude);
        if (!amplitudeTabular || !_writer)return false;
        bool isValid = false;

        //FITKAbaAmplitudeTabular
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::TimeSpan> fitkITSTypeTrafer;
        auto strTimeSpan = fitkITSTypeTrafer.toStrting(amplitudeTabular->getTimeSpan(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "TimeSpan", strTimeSpan.toStdString());

        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::SmoothingType> fitkISTTypeTrafer;
        auto strSmoothingType = fitkISTTypeTrafer.toStrting(amplitudeTabular->getSmoothingType(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "SmoothingType", strSmoothingType.toStdString());


        double SmoothingValue = amplitudeTabular->getSmoothingValue();
        writeDoubleAttribute(h5Group, "SmoothingValue", &SmoothingValue);

        Core::FITKEnumTransfer<Interface::FITKAbaAbstractAmplitude::BaselineCorrection> fitkIBCTypeTrafer;
        auto strBaseLineCorrection = fitkIBCTypeTrafer.toStrting(amplitudeTabular->getBaseLineCorrection(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "BaseLineCorrection", strBaseLineCorrection.toStdString());

        int NumberOfRows = amplitudeTabular->getNumberOfRows();
        writeIntAttribute(h5Group, "NumberOfRows", &NumberOfRows);
        for (int i = 0; i < NumberOfRows; ++i)
        {
            QString childName = "Rows_" + QString::number(i);
            auto child = h5Group.createGroup(childName.toStdString());

            double Time = amplitudeTabular->getTime(i);
            writeDoubleAttribute(child, "Time", &Time);
            double Amplitude = amplitudeTabular->getAmplitude(i);
            writeDoubleAttribute(child, "Amplitude", &Amplitude);
        }

        int NumberOfRowsOfMultipleIntervals = amplitudeTabular->getNumberOfRowsOfMultipleIntervals();
        writeIntAttribute(h5Group, "NumberOfRowsOfMultipleIntervals", &NumberOfRowsOfMultipleIntervals);
        for (int i = 0; i < NumberOfRowsOfMultipleIntervals; ++i)
        {
            auto child = h5Group.createGroup("MultipleIntervalRows_" + i);

            double MultipleInterval = amplitudeTabular->getMultipleInterval(i);
            writeDoubleAttribute(child, "MultipleInterval", &MultipleInterval);
        }

        return true;
    }

}
